package com.tian.service.impl;

import com.tian.entity.*;
import com.tian.enums.UserBalanceChangeTypeEnum;
import com.tian.mapper.*;
import com.tian.message.InvitedRegistryMessage;
import com.tian.service.UserInvitedRegistryService;
import com.tian.util.RedisConstantPre;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

/**
 * {@code @description:} TODO
 *
 * @author tianwc 公众号：Java后端技术全栈
 * 在线刷题 1200+java面试题和1000+篇技术文章：<a href="https://woaijava.cc/">博客地址</a>
 * {@code @date:} 2024-03-30 16:30
 * {@code @version:} 1.0
 */
@Slf4j
@Service
public class UserInvitedRegistryServiceImpl implements UserInvitedRegistryService {
    @Resource
    private ChargeUserMapper chargeUserMapper;
    @Resource
    private ChargeUserIncomeMapper chargeUserIncomeMapper;
    @Resource
    private ChargeInviteRecordMapper chargeInviteRecordMapper;
    @Resource
    private UserBalanceChangeRecordMapper userBalanceChangeRecordMapper;
    @Resource
    private RedissonClient redissonClient;

    @Transactional
    @Override
    public void invitedRegistry(InvitedRegistryMessage invitedRegistryMessage) {
        //防止重复消费
        int count = chargeInviteRecordMapper.countByReqId(invitedRegistryMessage.getReqId());
        if (count > 0) {
            log.info("【重复消费】，请求参数={}", invitedRegistryMessage);
            return;
        }
        //邀请记录
        ChargeInviteRecord chargeInviteRecord = new ChargeInviteRecord();
        Date date = new Date();
        chargeInviteRecord.setInvitedTime(date);
        chargeInviteRecord.setInvitedUserId(invitedRegistryMessage.getNewUserId());
        chargeInviteRecord.setInviteUserId(invitedRegistryMessage.getUserId());
        chargeInviteRecordMapper.insert(chargeInviteRecord);
        if (invitedRegistryMessage.getAmount().compareTo(BigDecimal.ZERO) <= 0) {
            return;
        }

        Long userId = invitedRegistryMessage.getUserId();

        RLock lock = redissonClient.getLock(RedisConstantPre.USER_INFO_ID_LOCK_PRE + userId);
        lock.lock();
        try {
            //邀请人余额 增加
            ChargeUser chargeUser = chargeUserMapper.selectByPrimaryKey(userId);
            BigDecimal beforeBalance = chargeUser.getBalance();
            BigDecimal afterBalance = beforeBalance.add(invitedRegistryMessage.getAmount());
            //新余额=当前余额+邀请收益
            chargeUser.setBalance(afterBalance);
            chargeUserMapper.updateByPrimaryKey(chargeUser);
            //邀请收益记录
            ChargeUserIncome chargeUserIncome = new ChargeUserIncome();
            chargeUserIncome.setIncome(invitedRegistryMessage.getAmount());
            chargeUserIncome.setUserId(invitedRegistryMessage.getUserId());
            chargeUserIncome.setCreateTime(date);
            //可以优化：0表示在途收益 1表示已获取收益（被邀请用户存在交易后）
            chargeUserIncome.setType(0);
            chargeUserIncomeMapper.insert(chargeUserIncome);
            //新增余额变更记录
            UserBalanceChangeRecord userBalanceChangeRecord = getUserBalanceChangeRecord(invitedRegistryMessage, beforeBalance, afterBalance);
            userBalanceChangeRecordMapper.insert(userBalanceChangeRecord);
        } finally {
            lock.unlock();
        }
    }

    private static UserBalanceChangeRecord getUserBalanceChangeRecord(InvitedRegistryMessage invitedRegistryMessage, BigDecimal beforeBalance, BigDecimal afterBalance) {
        UserBalanceChangeRecord userBalanceChangeRecord = new UserBalanceChangeRecord();
        userBalanceChangeRecord.setUserId(invitedRegistryMessage.getUserId());
        userBalanceChangeRecord.setOrderNo(invitedRegistryMessage.getReqId());
        userBalanceChangeRecord.setChangeType(UserBalanceChangeTypeEnum.USER_INVITE_USER.getType());
        userBalanceChangeRecord.setBeforeBalance(beforeBalance);
        userBalanceChangeRecord.setChangeBalance(invitedRegistryMessage.getAmount());
        userBalanceChangeRecord.setAfterBalance(afterBalance);
        userBalanceChangeRecord.setCreateTime(new Date());
        userBalanceChangeRecord.setRemark(UserBalanceChangeTypeEnum.USER_INVITE_USER.getDesc());
        return userBalanceChangeRecord;
    }
}
